#include "AITeamState.h"
#include "Timer.h"

AITeamState* AITeamState::instance = NULL;

AITeamState* AITeamState::GetInstance()
{
	if (instance == NULL)
	{
		instance = new AITeamState();
	}
	return instance;
}
void AITeamState::FreeInstance()
{
	if (instance != NULL)
		delete instance;
}

AITeamState::AITeamState(void)
{
	closestPeople = -1;
	sign = 0;
	timeCompleteAction = -1.0f;
}

AITeamState::~AITeamState(void)
{
	delete aiTeam;
}

std::vector<Player*> AITeamState::GetOpntTeam()
{
	return opnt_team;
}

void AITeamState::Init(FootBallMatch* _football)
{
	footBallMatch = _football;
	aiTeam = new OwerTeam();
	aiTeam->Init();
	currentSide = _football->TeamPlace();
	AIPlayer::ResetPosToShoot(currentSide);
	AIPlayer::InitPlayerType(currentSide);
	InitAreaActivite();
}

void AITeamState::Update(FootBallMatch* _football)
{
	//std::cout<<"Frame time:"<<Timer::FrameTime()<<std::endl;

	footBallMatch = _football;	
	team = _football->OwnerTeam();
	opnt_team = _football->OpntTeam();
	if (_football->TeamPlace() != currentSide)
	{
		currentSide = _football->TeamPlace();
		AIPlayer::ResetPosToShoot(currentSide);
		AIPlayer::InitPlayerType(currentSide);
	}
	Closet_Player = NULL;
	Opnt_Closet_Player = NULL;
	//Update State of match
	//GetAreaOfBall();
	//TimetoComplete Pass action, shoot
	if (checkTime)
	{
		if ( countTime < timeCompleteAction )
		{
			countTime += 0.1f;
		}
		else{
			checkTime = false;
		}
		std::cout<<"Count Time = "<<countTime<<" MaxTime: "<<timeCompleteAction<<std::endl;
	}
	CalAreaOfBall();
	Calc_Distant2Ball(_football);
	//Get value to aiTeam //position, closet
	aiTeam->Update();
	
	//Update to player
	std::vector<Player*>::iterator player;
	int i = 0;
	for(player = team.begin(); player != team.end(); player++)
	{
		/*if (aiTeam->myTeam[i].GetAction() == KICK)
			std::cout<<aiTeam->myTeam[i].GetTargetPos().x<<" , "<<aiTeam->myTeam[i].GetTargetPos().y<<" : "<<aiTeam->myTeam[i].GetFoce()<<" : "<<aiTeam->myTeam[i].GetAction()<<std::endl;*/
		(*player)->SetTarget(aiTeam->myTeam[i].GetTargetPos());
		(*player)->SetForce(aiTeam->myTeam[i].GetFoce());
		(*player)->SetAction(aiTeam->myTeam[i].GetAction());
		i++;
	}
	
	//Update Goal Keeper
	std::vector<Player*>::iterator it = team.begin();
	sign = (_football->TeamPlace()== LEFT)? -1: 1;
	bool enableKick = true, tmp = false;
	vector2d target;
	double R = 60.0;
	Ball* ball = _football->GameBall();
	vector2d I(PITCH_WIDTH / 2 + sign * PITCH_WIDTH / 2, PITCH_HEIGHT / 2);
	if ((*it)->Dist2Ball() <= k_control_len)
	{
		//Find target to KICK
		double maxDis = PITCH_WIDTH;
		int iToPass = -1;
		for (int i = 1; i < 5; i++)
		{
			vector2d dis = aiTeam->myTeam[i].GetPos() - (*it)->Pos();
			if (dis.Length() < maxDis)
			{
				//Check can pass
				bool canPass = true;
				vector<Player*>::iterator opnt_it;
				for(opnt_it= opnt_team.begin();opnt_it != opnt_team.end(); opnt_it++)
				{
					if((*opnt_it)->Pos().InsideRegion(aiTeam->myTeam[i].GetPos(), (*it)->Pos()))
					{
						canPass = false;
						break;
					}
				}
				if (canPass)
				{
					iToPass = i;
					maxDis = dis.Length();
				}
			}
		}
		if (iToPass != -1)
		{
			(*it)->SetTarget(aiTeam->myTeam[iToPass].GetPos());
		}
		else
		{
			(*it)->SetTarget(aiTeam->myTeam[3].GetFoce());
		}
		if ((_football->Goal_Team() - ball->Pos()).Length() < R)
		{
			(*it)->SetForce(10);
		}
		{
			(*it)->SetForce(k_move_foce);
		}
			(*it)->SetAction(KICK);
		//enableKick = false;
	}
	//else if ((_football->Goal_Team() - ball->Pos()).Length() < R) 
	//{
	//	//enableKick = false;
	//	(*it)->SetTarget(ball->Pos());
	//	(*it)->SetAction(MOVE);
	//	vector2d v_attarget= (*it)->Target() - (*it)->Pos();
	//	if(v_attarget.Length()<5 || (*it)->Dist2Ball() < 40) //This code to hold the Player stand at the Target.
	//	{
	//		(*it)->SetForce(1);
	//	}
	//	else if (v_attarget.Length()<10 || (*it)->Dist2Ball() < 45)
	//	{
	//		(*it)->SetForce(2);
	//	}			
	//	else if (v_attarget.Length()<15 || (*it)->Dist2Ball() < 50)
	//	{
	//		(*it)->SetForce(3);
	//	}
	//	else if (v_attarget.Length()<20 || (*it)->Dist2Ball() < 55)
	//	{
	//		(*it)->SetForce(4);
	//	}
	//	else
	//	{
	//		(*it)->SetForce(5);
	//	}
	//}
	else
	{
		//target.x = PITCH_WIDTH /2 + sign * 430.0f;
		vector2d Ball(_football->GameBall()->Pos().x, _football->GameBall()->Pos().y);
		float a, b, A, B, C, delta, x1, x2;
		a = (Ball.y - I.y) / (Ball.x - I.x);
		b = - I.x * (Ball.y - I.y) / (Ball.x - I.x) + I.y;
		A = a*a + 1;
		B = a * (b - I.y) - I.x;
		C = I.x * I.x + (b - I.y) * (b - I.y) - R * R;
		delta = B * B - A * C;
		x1 = (- B + sqrt(delta)) / A;
		x2 = (- B - sqrt(delta)) / A;
		target.x = (fabs(Ball.x - x1) < fabs(Ball.x - x2))? x1: x2;
		target.y = a * target.x + b;
		(*it)->SetTarget(target);
		(*it)->SetAction(MOVE);
		vector2d v_attarget= (*it)->Target() - (*it)->Pos();
		if(v_attarget.Length()<5 || (*it)->Dist2Ball() < 40) //This code to hold the Player stand at the Target.
		{
			(*it)->SetForce(1);
		}
		else if (v_attarget.Length()<10 || (*it)->Dist2Ball() < 45)
		{
			(*it)->SetForce(2);
		}			
		else if (v_attarget.Length()<15 || (*it)->Dist2Ball() < 50)
		{
			(*it)->SetForce(3);
		}
		else if (v_attarget.Length()<20 || (*it)->Dist2Ball() < 55)
		{
			(*it)->SetForce(4);
		}
		else
		{
			(*it)->SetForce(5);
		}
	}
}

/*************************************************
*	Calculate the Length to ball of Team players
***************************************************/
void AITeamState::Calc_Distant2Ball(FootBallMatch* _this )
{
	vector2d ball(_this->GameBall()->Pos());
	std::vector<Player*>::iterator player;
	double min_distant = PITCH_WIDTH;
	vector2d vector2ball;
	closestPeople = 0;
	double distance;
	int i = 0;
	for(player = team.begin();player != team.end();player++)
	{
		vector2ball = ball - (*player)->Pos();
		distance = vector2ball.Length();
		(*player)->SetDist2Ball(distance);
		aiTeam->myTeam[i].SetDistance2Ball(distance);

		if( distance <= min_distant )
		{
			Closet_Player = (*player);
			closestPeople = i;
			aiTeam->myTeam[i].isClosest = true;
			min_distant = distance;
		}
		else
		{
			aiTeam->myTeam[i].isClosest = false;
		}
		//Is control_len
		aiTeam->myTeam[i].hasBall = distance <= k_control_len ? true : false;
		//Set current position
		aiTeam->myTeam[i].SetPos((*player)->Pos());
		i++;
	}

	min_distant = PITCH_WIDTH;
	for(player = opnt_team.begin();player != opnt_team.end();player++)
	{
		vector2ball = ball - (*player)->Pos();
		(*player)->SetDist2Ball(vector2ball.Length());
		if(vector2ball.Length() <= min_distant )
		{
			Opnt_Closet_Player = (*player);
			min_distant = vector2ball.Length();
		}
	}

}
/*************************************************
*	Check which team is controling the Ball to set Team status Attack or Defend
***************************************************/
bool AITeamState::Is_Control_Ball(){
	if(Opnt_Closet_Player->Dist2Ball() > Closet_Player->Dist2Ball()) 
		return true;
	return false;
}


bool AITeamState::trong_vong_cam(FootBallMatch* _this)
{
	if (sign == -1)
	{
		if (_this->GameBall()->Pos().x < 70 && _this->GameBall()->Pos().y >= (PITCH_WIDTH / 2 - 165) && _this->GameBall()->Pos().y <= (PITCH_WIDTH / 2 + 165))
		{
			return true;
		}
	}
	else if(sign == 1)
	{
		if (_this->GameBall()->Pos().x > (PITCH_WIDTH - 70) && _this->GameBall()->Pos().y >= (PITCH_WIDTH / 2 - 165) && _this->GameBall()->Pos().y <= (PITCH_WIDTH / 2 + 165))
		{
			return true;
		}
	}
	return false;
}

STATEMATCH AITeamState::GetState()
{
	if (Closet_Player->Dist2Ball() < Opnt_Closet_Player->Dist2Ball())
	{
		if ((Closet_Player->Dist2Ball() < k_control_len) ||  (checkTime && (countTime < 0.5f * timeCompleteAction)))
		{
			state = ATTACKSTATE;
		}
		else{
			state = INDENTIFYSTATE;
			checkTime = false;
		}
	}
	else
	{
		if ((Opnt_Closet_Player->Dist2Ball() < k_control_len) || (checkTime && (countTime > 0.5f * timeCompleteAction)))
			state = DEFENCESTATE;
		else{
			state = INDENTIFYSTATE;
			checkTime = false;
		}
	}
	return state;
}

void AITeamState::InitAreaActivite()
{
	areaActivite[GOAL_KEEPER] = vector2d(PITCH_WIDTH/2, PITCH_HEIGHT/2);
	areaActivite[LEFTPLAYER] = areaActivite[RIGHTPLAYER] = areaActivite[ATTACKPLAYERRIGHT] = areaActivite[ATTACKPLAYERLEFT] = vector2d(PITCH_WIDTH/4, PITCH_HEIGHT/6);
	areaActivite[CENTERPLAYER] = areaActivite[DEFENCEPLAYER] = areaActivite[ATTACKPLAYER] = vector2d(PITCH_WIDTH/6, PITCH_HEIGHT/6);
}

PLAYERTYPE AITeamState::GetAreaOfBall()
{
	return areaOfBall;
}

void AITeamState::CalAreaOfBall()
{
	vector2d ballPos = footBallMatch->GameBall()->Pos();
	areaOfBall = GOALKEEPER;
	for (int i = 1; i < MAX_PLAYER_TYPE; i++)
	{
		vector2d vec2Ball = AIPlayer::GetPositionOfType((PLAYERTYPE)i) - ballPos;
		if (fabs(vec2Ball.x) <= areaActivite[i].x && fabs(vec2Ball.y) <= areaActivite[i].y)
		{
			areaOfBall = (PLAYERTYPE)i;
			break;
		}
	}
	std::cout<<"Area of ball:"<<areaOfBall<<std::endl;
}

void AITeamState::ResetTimeCount(double maxTime)
{
	timeCompleteAction = maxTime;
	countTime = 0.0f;
	checkTime = true;
}